﻿/*
 * Ast classes for Ast of the ebnf
 */ 
using System.Collections.Generic;

namespace EbnfStudio
{

    /// <summary>
    /// Visitor design pattern for traversing the ast tree
    /// </summary>
    public interface IAstVisitor
    {
        void Visit(AstSyntax ast);
        void Visit(AstRule ast);
        void Visit(AstExpression ast);
        void Visit(AstTerm ast);
        void Visit(AstEmptyFactor ast);
        void Visit(AstIdentifier ast);
        void Visit(AstLiteral ast);
        void Visit(AstGroup ast);
        void Visit(AstOptional ast);
        void Visit(AstRepetition ast);
    }


    /// <summary>
    /// Base interface for Ast nodes
    /// </summary>
    public interface IAst
    {
        // Visitor pattern
        void Accept(IAstVisitor visitor);
    }


    /// <summary>
    /// the factor interface
    /// </summary>
    public interface IAstFactor : IAst { }


    /// <summary>
    /// collection of statement
    /// </summary>
    public class AstSyntax : IAst
    {
        // visitor pattern
        public virtual void Accept(IAstVisitor visitor) { visitor.Visit(this); }

        // the statements
        public List<AstRule> Rules { get; set; }

        // constructor
        public AstSyntax(List<AstRule> rules)
        {
            Rules = rules;
        }
    }


    /// <summary>
    /// Assign statement
    /// </summary>
    public class AstRule : IAst
    {
        // visitor pattern
        public virtual void Accept(IAstVisitor visitor) { visitor.Visit(this); }

        // the identifier
        public Token Identifier { get; set; }

        // the expression
        public AstExpression Expression { get; set; }

        // constructor
        public AstRule(Token id, AstExpression expression)
        {
            Identifier = id; Expression = expression;
        }
    }


    /// <summary>
    /// the expression
    /// </summary>
    public class AstExpression : IAst
    {
        // visitor pattern
        public virtual void Accept(IAstVisitor visitor) { visitor.Visit(this); }

        // list of terminals
        public List<AstTerm> Terms { get; set; }

        // constructor
        public AstExpression(List<AstTerm> terms)
        {
            Terms = terms;
        }
    }


    /// <summary>
    /// The terminals
    /// </summary>
    public class AstTerm : IAst
    {
        // visitor pattern
        public virtual void Accept(IAstVisitor visitor) { visitor.Visit(this); }

        // list of terminals
        public List<IAstFactor> Factors { get; set; }

        // constructor
        public AstTerm(List<IAstFactor> factors)
        {
            Factors = factors;
        }
    }


    /// <summary>
    /// Empty production node
    /// </summary>
    public class AstEmptyFactor : IAstFactor
    {
        // visitor pattern
        public virtual void Accept(IAstVisitor visitor) { visitor.Visit(this); }

        // automatically generated or read ?
        public bool Automatic { get; set; }

        // constructor
        public AstEmptyFactor(bool automatic)
        {
            Automatic = automatic;
        }
    }


    /// <summary>
    /// identifier
    /// </summary>
    public class AstIdentifier : IAstFactor
    {
        // visitor pattern
        public virtual void Accept(IAstVisitor visitor) { visitor.Visit(this); }

        // the identifier
        public Token Identifier { get; set; }

        // constructor
        public AstIdentifier(Token identifier)
        {
            Identifier = identifier;
        }
    }


    /// <summary>
    /// literal
    /// </summary>
    public class AstLiteral : IAstFactor
    {
        // visitor pattern
        public virtual void Accept(IAstVisitor visitor) { visitor.Visit(this); }

        // the literal
        public Token Literal { get; set; }

        // invalid literal
        public bool Invalid { get; set; }

        // constructor
        public AstLiteral(Token literal, bool invalid)
        {
            Literal = literal;
            Invalid = invalid;
        }
    }


    /// <summary>
    /// the group
    /// </summary>
    public class AstGroup : IAstFactor
    {
        // visitor pattern
        public virtual void Accept(IAstVisitor visitor) { visitor.Visit(this); }

        // the expression
        public AstExpression Expression { get; set; }

        // constructor
        public AstGroup(AstExpression expression)
        {
            Expression = expression;
        }
    }


    /// <summary>
    /// the optional
    /// </summary>
    public class AstOptional : IAstFactor
    {
        // visitor pattern
        public virtual void Accept(IAstVisitor visitor) { visitor.Visit(this); }

        // the expression
        public AstExpression Expression { get; set; }

        // constructor
        public AstOptional(AstExpression expression)
        {
            Expression = expression;
        }
    }


    /// <summary>
    /// the optional
    /// </summary>
    public class AstRepetition : IAstFactor
    {
        // visitor pattern
        public virtual void Accept(IAstVisitor visitor) { visitor.Visit(this); }

        // the expression
        public AstExpression Expression { get; set; }

        // constructor
        public AstRepetition(AstExpression expression)
        {
            Expression = expression;
        }
    }
}
